﻿//-----------------------------------------------------------------------
// <copyright>
// This file is subject to the terms and conditions of the Microsoft Public License (MS-PL).
// See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL for more details.
// </copyright>
//----------------------------------------------------------------------- 
using System;
using System.Xml.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Fulcrum.ViewModelGenerator.UnitTests
{
    [TestClass]
    public class XElementExtensionsTests
    {
        #region RequiredAttribute

        [TestMethod]
        public void XElementExtensions_RequiredAttribute_NullElementArgument()
        {
            try
            {
                XElementExtensions.RequiredAttribute(null, null);
            }
            catch (ArgumentNullException e)
            {
                Assert.AreEqual<string>("element", e.ParamName);
                return;
            }

            Assert.Fail();
        }

        [TestMethod]
        public void XElementExtensions_RequiredAttribute_NullNameArgument()
        {
            try
            {
                new XElement("Name").RequiredAttribute(null);
            }
            catch (ArgumentNullException e)
            {
                Assert.AreEqual<string>("name", e.ParamName);
                return;
            }

            Assert.Fail();
        }

        [TestMethod]
        public void XElementExtensions_RequiredAttribute_NoAttribute()
        {
            try
            {
                new XElement("Name").RequiredAttribute("UnavailableAttribute");
            }
            catch (ArgumentNullException e)
            {
                Assert.AreEqual<string>("UnavailableAttribute", e.ParamName);
                return;
            }

            Assert.Fail();
        }

        [TestMethod]
        public void XElementExtensions_RequiredAttribute_EmptyValueAttribute()
        {
            try
            {
                new XElement("Name",
                    new XAttribute("Attribute", "  ")).RequiredAttribute("Attribute");
            }
            catch (ArgumentNullException e)
            {
                Assert.AreEqual<string>("Attribute", e.ParamName);
                return;
            }

            Assert.Fail();
        }

        [TestMethod]
        public void XElementExtensions_RequiredAttribute_AttributeWithValue()
        {
            string attributeValue = "Name";

            var value = (string)new XElement("Name",
                new XAttribute("Attribute", attributeValue)).RequiredAttribute("Attribute");

            Assert.AreEqual<string>(attributeValue, value);
        }

        [TestMethod]
        public void XElementExtensions_RequiredAttribute_AttributeWithNonStringValue()
        {
            bool attributeValue = true;
            string attributeStringValue = "true";

            var value = (string)new XElement("Name",
                new XAttribute("Attribute", attributeValue)).RequiredAttribute("Attribute");

            Assert.AreEqual<string>(attributeStringValue, value);
        }

        #endregion RequiredAttribute

        #region OptionalAttribute

        [TestMethod]
        public void XElementExtensions_OptionalAttribute_NullElementArguments()
        {
            try
            {
                XElementExtensions.OptionalAttribute(null, null, null);
            }
            catch (ArgumentNullException e)
            {
                Assert.AreEqual<string>("element", e.ParamName);
                return;
            }

            Assert.Fail();
        }

        [TestMethod]
        public void XElementExtensions_OptionalAttribute_NullNameArguments()
        {
            try
            {
                new XElement("Element").OptionalAttribute(null, null);
            }
            catch (ArgumentNullException e)
            {
                Assert.AreEqual<string>("name", e.ParamName);
                return;
            }

            Assert.Fail();
        }

        [TestMethod]
        public void XElementExtensions_OptionalAttribute_HasAttribute()
        {
            string expected = "Attribute Value";
            string unexpected = "Default value";

            var attribute = new XElement("Element",
                new XAttribute("Attribute", expected)).OptionalAttribute("Attribute", unexpected);

            Assert.AreEqual<string>(expected, attribute.Value);
        }

        [TestMethod]
        public void XElementExtensions_OptionalAttribute_DoesNotHaveAttribute()
        {
            string expected = "Default value";

            var attribute = new XElement("Element").OptionalAttribute("Attribute", expected);

            Assert.AreEqual<string>(expected, attribute.Value);
        }

        #endregion OptionalAttribute

        #region OptionalEnumAttribute

        [TestMethod]
        public void XElementExtensions_OptionalEnumAttribute_NullElementArguments()
        {
            try
            {
                XElementExtensions.OptionalEnumAttribute<StringComparison>(null, null, StringComparison.CurrentCulture);
            }
            catch (ArgumentNullException e)
            {
                Assert.AreEqual<string>("element", e.ParamName);
                return;
            }

            Assert.Fail();
        }

        [TestMethod]
        public void XElementExtensions_OptionalEnumAttribute_NullNameArguments()
        {
            try
            {
                new XElement("Element").OptionalEnumAttribute<StringComparison>(null, StringComparison.CurrentCulture);
            }
            catch (ArgumentNullException e)
            {
                Assert.AreEqual<string>("name", e.ParamName);
                return;
            }

            Assert.Fail();
        }

        [TestMethod]
        public void XElementExtensions_OptionalEnumAttribute_HasAttribute()
        {
            var expected = StringComparison.InvariantCulture;
            var unexpected = StringComparison.CurrentCulture;

            var attribute = new XElement("Element",
                new XAttribute("Attribute", expected.ToString())).OptionalEnumAttribute<StringComparison>("Attribute", unexpected);

            Assert.AreEqual(expected, attribute);
        }

        [TestMethod]
        public void XElementExtensions_OptionalEnumAttribute_HasInvalidAttribute()
        {
            try
            {
                var unexpected = StringComparison.CurrentCulture;

                var attribute = new XElement("Element",
                    new XAttribute("Attribute", "InvalidEnumValue")).OptionalEnumAttribute<StringComparison>("Attribute", unexpected);
            }
            catch (ArgumentException e)
            {
                Assert.AreEqual(null, e.ParamName);
                return;
            }

            Assert.Fail();
        }


        [TestMethod]
        public void XElementExtensions_OptionalEnumAttribute_DoesNotHaveAttribute()
        {
            var expected = StringComparison.CurrentCultureIgnoreCase;

            var attribute = new XElement("Element").OptionalEnumAttribute<StringComparison>("Attribute", expected);

            Assert.AreEqual(expected, attribute);
        }

        #endregion OptionalEnumAttribute
    }
}
